package linkedlist;

/**
 * 链表：
 * 增删改查
 * 反转链表
 *
 * @author shkstart
 * @create 2021-04-26 14:34
 */
public class SingleLinkedListDemo {

    public static void main(String[] args) {
        HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
        HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
        HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
        HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");

        SingleLinkedList singleLinkedList = new SingleLinkedList();
//加入
        singleLinkedList.add(hero1);
        singleLinkedList.add(hero2);
        singleLinkedList.add(hero3);
        singleLinkedList.add(hero4);
//遍历
        singleLinkedList.list();
//修改
        HeroNode heroNode = new HeroNode(4, "冲冲", "爆炸头");
        singleLinkedList.update(heroNode);
//反转
        HeroNode recursion = singleLinkedList.recursion(hero1);
        HeroNode temp = recursion;
//        遍历反转
        while (true) {
//判断是否到链表最后
            if (temp == null) {
                break;
            }
//输出节点的信息
            System.out.println(temp);
//将temp 后移， 一定小心
            temp = temp.next;

        }


    }
}

//定义SingleLinkedList 管理我们的英雄
class SingleLinkedList { //先初始化一个头节点, 头节点不要动, 不存放具体的数据
    private HeroNode head = new HeroNode(0, "", "");

    //添加节点到单向链表
    public void add(HeroNode heroNode) {
        //思路，当不考虑编号顺序时
        //1. 找到当前链表的最后节点
        //2. 将最后这个节点的next 指向新的节点
        //因为head 节点不能动，因此我们需要一个辅助遍历temp
        HeroNode temp = head;
        //遍历链表，找到最后
        while (true) {
            //找到链表的最后
            if (temp.next == null) {
                break;
            }
//如果没有找到最后, 将将temp 后移
            temp = temp.next;
        }
//当退出while 循环时，temp 就指向了链表的最后
//将最后这个节点的next 指向新的节点
        temp.next = heroNode;
    }

    // 遍历链表
    public void list() {
//判断链表是否为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
//因为头节点，不能动，因此我们需要一个辅助变量来遍历
        HeroNode temp = head.next;
        while (true) {
//判断是否到链表最后
            if (temp == null) {
                break;
            }
//输出节点的信息
            System.out.println(temp);
//将temp 后移， 一定小心
            temp = temp.next;
        }
    }

    //修改节点的信息,
    public void update(HeroNode newHeroNode) {
        //1. 根据newHeroNode 的no 来修改即可
//判断是否空
        if (head.next == null) {
            System.out.println("链表为空~");
            return;
        }
//找到需要修改的节点, 根据no 编号
//定义一个辅助变量
        HeroNode temp = head.next;
        boolean flag = false; //表示是否找到该节点
        while (true) {
            if (temp == null) {
                break; //已经遍历完链表
            }
            if (temp.no == newHeroNode.no) {
                //找到
                flag = true;
                break;
            }
            temp = temp.next;
        }
//根据flag 判断是否找到要修改的节点
        if (flag) {
            temp.name = newHeroNode.name;
            temp.nickname = newHeroNode.nickname;
        } else { //没有找到
            System.out.printf("没有找到编号%d 的节点，不能修改\n", newHeroNode.no);
        }
    }

    public void update1(HeroNode heroNode) {
        if (head.next == null) {
            return;
        }
        HeroNode item = head.next;
        boolean fls = false;
        while (true) {
            if (item == null) {
                break;
            } else if (item.no == heroNode.no) {
                fls = true;
                break;
            }
            item = item.next;
        }
        if (fls) {
            item.name = heroNode.name;
            item.nickname = heroNode.nickname;
        } else {
            System.out.printf("没有找到编号%d 的节点，不能修改\n", heroNode.no);

        }

    }

    // 反转
    public HeroNode recursion(HeroNode head) {
        if (head == null || head.next == null) {
            return head;  //返回最后一个节点
        }
        HeroNode new_head = recursion(head.next);
        head.next.next = head; //5的指针指向4
        head.next = null;   //4的指针指向空
        return new_head;

    }

    //删除节点
    public void del(int no) {
        //思路
//1. head 不能动，因此我们需要一个temp 辅助节点找到待删除节点的前一个节点
//2. 说明我们在比较时，是temp.next.no 和需要删除的节点的no 比较
        HeroNode temp = head;
        boolean flag = false; // 标志是否找到待删除节点的
        while (true) {
            if (temp.next == null) { //已经到链表的最后
                break;
            }
            if (temp.next.no == no) {
//找到的待删除节点的前一个节点temp
                flag = true;
                break;
            }
            temp = temp.next; //temp 后移，遍历
        }
//判断flag
        if (flag) { //找到
//可以删除
            temp.next = temp.next.next;
        } else {
            System.out.printf("要删除的%d 节点不存在\n", no);
        }
    }
}

//定义HeroNode ， 每个HeroNode 对象就是一个节点
class HeroNode {
    public int no;
    public String name;
    public String nickname;
    public HeroNode next; //指向下一个节点

    //构造器
    public HeroNode(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    //为了显示方法，我们重新toString
    @Override
    public String toString() {
        return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
    }
}

